package net.yxsoft.model.infrastructure.base;

import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.ActiveRecordException;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Table;
import com.jfinal.plugin.activerecord.TableMapping;
import rapid.core.ContextStateEnum;
import rapid.core.ExceptionDescriptor;
import rapid.core.TResult;

import java.sql.SQLException;
import java.util.Date;
import java.util.UUID;

public class BaseModel<M extends Model> extends Model<M> {
  private static TResult result=new TResult();
  /**
   * 保存
   */
  @Override
  public boolean save() {
    String pk = null;
    Table table = TableMapping.me().getTable(getClass());
    pk = table.getPrimaryKey()[0];
    // 序列默认值
    if (this.get(pk) == null) {
      if (table.getColumnType(pk).getSimpleName().equals("BigDecimal")) {
        this.set(pk, "SEQ_" + table.getName() + ".nextval");
      }
      if(table.getColumnType(pk).getSimpleName().equals("String")){

        String _key = UUID.randomUUID().toString().replace("-", "");
        this.set(pk, _key);
        try {
          if (this.get("row_id") == null || StrKit.isBlank(this.getStr("row_id"))) {
            this.set("row_id", _key);
          }
        } catch (Exception ex) {
        }
      }
    }

      boolean isSave = super.save();


    //this.set("row_id",this.getPKValue());
    //super.update();

    return isSave;
  }


/**
* @MethodName: saveWithExceptionHandling
* @Description: 保存
* @param:
* @return rapid.core.TResult
* @throws
* @date 2023/11/14 11:40
* @author wj
*/
  public TResult saveWithExceptionHandling() {
    String pk = null;
    Table table = TableMapping.me().getTable(getClass());
    pk = table.getPrimaryKey()[0];
    // 序列默认值
    if (this.get(pk) == null) {
      if (table.getColumnType(pk).getSimpleName().equals("BigDecimal")) {
        this.set(pk, "SEQ_" + table.getName() + ".nextval");
      }
      if(table.getColumnType(pk).getSimpleName().equals("String")){

        String _key = UUID.randomUUID().toString().replace("-", "");
        this.set(pk, _key);
        try {
          if (this.get("row_id") == null || StrKit.isBlank(this.getStr("row_id"))) {
            this.set("row_id", _key);
          }
        } catch (Exception ex) {
        }
      }
    }

    try {
      boolean  isSave= super.save();
      result.setState(ContextStateEnum.SUCCESS);
      result.setData(isSave);
      result.setMessage(null);
    }catch (Exception e){
      result= setError(e);
    }

    //this.set("row_id",this.getPKValue());
    //super.update();

    return result;
  }


  /**
   * 保存或提交
   */

  public TResult saveOrUpdateWithExceptionHandling() {
    String pk = null;
    Table table = TableMapping.me().getTable(getClass());
    pk = table.getPrimaryKey()[0];
    boolean isSave=false;
    // 序列默认值
    if (this.get(pk) == null) {
      this.set("created", new Date(System.currentTimeMillis()));

      if (table.getColumnType(pk).getSimpleName().equals("BigDecimal")) {
        this.set(pk, "SEQ_" + table.getName() + ".nextval");
      }
      if(table.getColumnType(pk).getSimpleName().equals("String")){

        String _key = UUID.randomUUID().toString().replace("-", "");
        this.set(pk, _key);
        try {
          if (this.get("row_id") == null || StrKit.isBlank(this.getStr("row_id"))) {
            this.set("row_id", _key);
          }
        } catch (Exception ex) {
        }
      }


      try {
          isSave= super.save();
        result.setState(ContextStateEnum.SUCCESS);
        result.setData(isSave);
        result.setMessage(null);
      }catch (Exception e){
        result= setError(e);
      }
    }else{
      this.set("last_upd", new Date(System.currentTimeMillis()));
      try {
        isSave= super.update();
        result.setState(ContextStateEnum.SUCCESS);
        result.setData(isSave);
        result.setMessage(null);
      }catch (Exception e){
        result= setError(e);
      }
    }

    return result;
  }

  /**
   * @MethodName: setError
   * @Description: 错误信息收集
   * @param: e
   * @return void
   * @throws
   * @date 2023/11/14 9:59
   * @author wj
   */
  private static TResult setError(Exception e){
    if (e instanceof ActiveRecordException) {
      ActiveRecordException activeRecordException = (ActiveRecordException) e;
      Throwable cause = activeRecordException.getCause();

      // 判断异常类型并进行处理
      if (cause instanceof SQLException) {
        SQLException sqlException = (SQLException) cause;
        int errorCode = sqlException.getErrorCode();
        String sqlState = sqlException.getSQLState();
        // 判断异常类型并进行处理
        if (errorCode == 1040 ) {
          // SQL 语句格式错误异常处理
          return  handleError("当前连接到数据库的连接数超过了数据库允许的最大连接数。" , e);
        }else if (errorCode == 1042 ) {
          // SQL 语句格式错误异常处理
          return  handleError("表示无法连接到指定的 MySQL 主机。" , e);
        }else if (errorCode == 1045 ) {
          // SQL 语句格式错误异常处理
          return  handleError("表示数据库连接时使用的用户名或密码不正确。" , e);
        }else if (errorCode == 1406) {
          // 字段超出长度异常处理
          String columnName = getColumnNameFromError(sqlException.getMessage());
          return  handleError("字段超出长度错误，字段名：" + columnName, e);
        }else if (errorCode == 1364) {
          // 字段超出长度异常处理
          String columnName = getColumnNameFromError(sqlException.getMessage());
          return  handleError("未为非空字段提供默认值，字段名：" + columnName, e);
        }else if (errorCode == 1451) {
          // 字段超出长度异常处理
          return  handleError("违反了外键约束，修改或删除的行被其他表的外键引用。" , e);
        } else if (errorCode == 2013) {
          // 字段超出长度异常处理
          return  handleError("在执行查询过程中失去了与 MySQL 服务器的连接。" , e);
        }   else if (errorCode == 1366) {
          // 数据类型转换错误异常处理
          return handleError("数据类型转换错误", e);
        } else if (errorCode == 1064) {
          // SQL 语句格式错误异常处理
          return  handleError("SQL 语句格式错误", e);
        } else if (errorCode == 1054 ) {
          // SQL 语句格式错误异常处理
          String columnName = getColumnNameFromError(sqlException.getMessage());
          return  handleError("字段不存在，字段名：" + columnName, e);
        } else if (errorCode == 0) {
          // SQL 语句格式错误异常处理
          return  handleError("SQL 语句格式错误", e);
        }
      }
    }

    // 其他异常类型，进行处理
    return handleError("未处理的异常：" + e.getMessage(), e);
  }
  /**
   * 保存或提交
   */

  public boolean saveOrUpdate() {
    String pk = null;
    Table table = TableMapping.me().getTable(getClass());
    pk = table.getPrimaryKey()[0];
    boolean isSave=false;
    // 序列默认值
    if (this.get(pk) == null) {
      this.set("created", new Date(System.currentTimeMillis()));

      if (table.getColumnType(pk).getSimpleName().equals("BigDecimal")) {
        this.set(pk, "SEQ_" + table.getName() + ".nextval");
      }
      if(table.getColumnType(pk).getSimpleName().equals("String")){

        String _key = UUID.randomUUID().toString().replace("-", "");
        this.set(pk, _key);
        try {
          if (this.get("row_id") == null || StrKit.isBlank(this.getStr("row_id"))) {
            this.set("row_id", _key);
          }
        } catch (Exception ex) {
        }
      }
       isSave = super.save();
    }else{
      this.set("last_upd", new Date(System.currentTimeMillis()));
      isSave = super.update();
    }



    return isSave;
  }

  /**
   * 获取主键值：非复合主键
   *
   * @return
   */
  public String getPKValue() {
    String[] pkNameArr = getTable().getPrimaryKey();
    if (pkNameArr.length == 1) {
      return this.getStr(pkNameArr[0]);
    } else {
      String pk = "";
      for (String pkName : pkNameArr) {
        pk += this.get(pkName) + ",";
      }
      return pk;
    }
  }

  /**
   * 获取表映射对象
   *
   * @return
   */
  protected Table getTable() {
    return TableMapping.me().getTable(getClass());
  }

  /**
   * 获取表名称
   *
   * @return
   */
  protected String getTableName() {
    return getTable().getName();
  }

  private static String getColumnNameFromError(String errorMessage) {
    // 解析错误信息，获取字段名
    String columnName = errorMessage.split("'")[1];
    return columnName;
  }

  /**
   * @MethodName: handleError
   * @Description: 错误信息返回
   * @param: errorMessage
   * @param: e
   * @return rapid.core.TResult
   * @throws
   * @date 2023/11/14 10:00
   * @author wj
   */
  private static TResult handleError(String errorMessage, Exception e) {
    result.setState(ContextStateEnum.FAIL);
    result.setMessage(errorMessage);
    result.setException(new ExceptionDescriptor(e));
    return result;
  }
}
